模型选择:选择估计器及其参数
分数和交叉验证的分数
如我们所见,每个估计器都有一个score
可以判断新数据的拟合(或预测)程度的方法。该值越大越好。
>>> from sklearn import datasets, svm
>>> X_digits, y_digits = datasets.load_digits(return_X_y=True)
>>> svc = svm.SVC(C=1, kernel='linear')
>>> svc.fit(X_digits[:-100], y_digits[:-100]).score(X_digits[-100:], y_digits[-100:])
0.98
为了更好地衡量预测的准确度(我们可以将预测的准确度认为是模型拟合程度的指标),我们可以将数据分多个fold,用于训练和测试:
>>> import numpy as np
>>> X_folds = np.array_split(X_digits, 3)
>>> y_folds = np.array_split(y_digits, 3)
>>> scores = list()
>>> for k in range(3):
... # 我们使用 'list' 去复制, 为了后面可以使用'pop'方法
... X_train = list(X_folds)
... X_test = X_train.pop(k)
... X_train = np.concatenate(X_train)
... y_train = list(y_folds)
... y_test = y_train.pop(k)
... y_train = np.concatenate(y_train)
... scores.append(svc.fit(X_train, y_train).score(X_test, y_test))
>>> print(scores)
[0.934..., 0.956..., 0.939...]
这称为KFold
交叉验证。
交叉验证生成器
Scikit-learn具有一组类,这些类可用于根据流行的交叉验证策略来生成训练/测试索引列表。
他们都有split
方法,该方法接收要拆分的数据集,并根据所选的交叉验证策略,每次迭代生成训练/测试集的索引。
本示例显示了该split
方法的使用。
>>> from sklearn.model_selection import KFold, cross_val_score
>>> X = ["a", "a", "a", "b", "b", "c", "c", "c", "c", "c"]
>>> k_fold = KFold(n_splits=5)
>>> for train_indices, test_indices in k_fold.split(X):
... print('Train: %s | test: %s' % (train_indices, test_indices))
Train: [2 3 4 5 6 7 8 9] | test: [0 1]
Train: [0 1 4 5 6 7 8 9] | test: [2 3]
Train: [0 1 2 3 6 7 8 9] | test: [4 5]
Train: [0 1 2 3 4 5 8 9] | test: [6 7]
Train: [0 1 2 3 4 5 6 7] | test: [8 9]
然后可以轻松执行交叉验证:
>>> [svc.fit(X_digits[train], y_digits[train]).score(X_digits[test], y_digits[test])
... for train, test in k_fold.split(X_digits)]
[0.963..., 0.922..., 0.963..., 0.963..., 0.930...]
可以使用cross_val_score
方法可以直接计算交叉验证的分数 。需要给定一个估计器,交叉验证对象和数据集,cross_val_score
将数据集重复拆分为训练集和测试集,使用训练集训练估计器,并根据测试集为交叉验证的每次迭代计算分数。
默认情况下,cross_val_score
使用估计器的score
方法来计算各个分数。
请参阅测量模块以了解有关可用计算分数方法的更多信息。
>>> cross_val_score(svc, X_digits, y_digits, cv=k_fold, n_jobs=-1)
array([0.96388889, 0.92222222, 0.9637883 , 0.9637883 , 0.93036212])
n_jobs=-1
意味着计算机的所有CPU都将参与运算。
或者,可以改变scoring
的值以修改评分方法。
>>> cross_val_score(svc, X_digits, y_digits, cv=k_fold,
... scoring='precision_macro')
array([0.96578289, 0.92708922, 0.96681476, 0.96362897, 0.93192644])
交叉验证生成器
KFold
(n_splits, shuffle, random_state)
将数据集拆分为K份,在K-1份上训练,然后在剩下的第K份上进行测试。
StratifiedKFold
(n_splits, shuffle, random_state)
与KFold相同,但保留每个份内的类别分布
GroupKFold
(n_splits)
确保同一组数据不会同时在训练集和测试集中。
ShuffleSplit
(n_splits, test_size, train_size, random_state)
随机生成训练/测试索引。
与shuffleSplit相同,但保留每次迭代内的类别分布。
确保同一组数据不会同时在训练集和测试集中。
采用数组对组进行观察。
LeavePGroupsOut
(n_groups)
忽略P组。
LeaveOneOut
()
忽略一个观察组。
LeavePOut
(p)
忽略P个观测值。
根据预定义的拆分策略生成训练/测试索引。
练习
在手写数字识别数据集上,绘制参数是C
的线性核SVC
的交叉验证的分数(使用对数网格,从1到10)。
import numpy as np
from sklearn.model_selection import cross_val_score
from sklearn import datasets, svm
X, y = datasets.load_digits(return_X_y=True)
svc = svm.SVC(kernel='linear')
C_s = np.logspace(-10, 0, 10)
scores = list()
网格搜索和交叉验证估计器
网格搜索
scikit-learn提供了一个对象,该对象在给定数据的情况下,在参数网格上训练估计器和计算分数,并选择参数以最大化交叉验证的分数。该对象在创建过程中接收一个估计器对象,并提供一个估计器的API:
>>> from sklearn.model_selection import GridSearchCV, cross_val_score
>>> Cs = np.logspace(-6, -1, 10)
>>> clf = GridSearchCV(estimator=svc, param_grid=dict(C=Cs),
... n_jobs=-1)
>>> clf.fit(X_digits[:1000], y_digits[:1000])
GridSearchCV(cv=None,...
>>> clf.best_score_
0.925...
>>> clf.best_estimator_.C
0.0077...
>>> # 测试集上的预测结果没有在训练集上面的好
>>> clf.score(X_digits[1000:], y_digits[1000:])
0.943...
默认情况下,GridSearchCV
使用3-fold交叉验证。但是,如果检测到接收的是分类器而不是回归器,则使用分层的3-fold。默认值将在版本0.22中更改为5-fold交叉验证。
嵌套交叉验证
>>> cross_val_score(clf, X_digits, y_digits)
array([0.938..., 0.963..., 0.944...])
并行执行两个交叉验证循环:一个是 GridSearchCV
估计器来设置gamma
,另一个是 cross_val_score
测量估计器的预测性能。所得分数是对新数据的预测分数的无偏估计。
警告
您不能使用并行计算(n_jobs
不等于1)嵌套对象。
交叉验证的估计器
可以在逐个算法的基础上更高效地完成交叉验证以设置参数。这就是为什么对于某些估计器,scikit-learn会提供交叉验证:评估估计器的性能 估计器,这些估计器可以通过交叉验证自动设置其参数。
>>> from sklearn import linear_model, datasets
>>> lasso = linear_model.LassoCV()
>>> X_diabetes, y_diabetes = datasets.load_diabetes(return_X_y=True)
>>> lasso.fit(X_diabetes, y_diabetes)
LassoCV()
>>> # 估计器会自动选择它的lambda值:
>>> lasso.alpha_
0.00375...
这些交叉验证估计器的名称与估计器的名称相似,所以在它们的名字后面有“CV”。
练习
在糖尿病数据集上,找到最佳正则化参数alpha。
奖励 : 您对所选择的alpha参数的值有多相信?
from sklearn import datasets
from sklearn.linear_model import LassoCV
from sklearn.linear_model import Lasso
from sklearn.model_selection import KFold
from sklearn.model_selection import GridSearchCV
X, y = datasets.load_diabetes(return_X_y=True)
X = X[:150]
答案: 糖尿病数据集练习的交叉验证
©2007-2019,scikit-learn开发人员(BSD许可证)。 显示此页面源码